/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1/commercial
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may use this file in compliance with the License.
 * Alternatively, if you can't copy with the License, namely if you do not
 * want to provide source code of your modifications to this file, you may
 * negotiate a commercial licence with the initial developer.
 * You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is COID.
 *
 * The Initial Developer of the Original Code is
 * Brano Kemen.
 * Portions created by the Initial Developer are Copyright (C) 2006
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 * Brano Kemen
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#ifndef __MOD_COID__HTTPSTREAMAPACHE__HEADER_FILE__
#define __MOD_COID__HTTPSTREAMAPACHE__HEADER_FILE__

#include "coid/comm/binstream/httpstreamcoid.h"

#include "apachefix.h"
#include <http_protocol.h>
#include <ap_compat.h>

using namespace coid;

////////////////////////////////////////////////////////////////////////////////
class httpstreamapache : public httpstreamcoid
{
    request_rec *rec;
    int wstatus;

    charstr tmpssid;

public:

    httpstreamapache()
    {
        rec = 0;
        wstatus = 0;
    }

    void set( request_rec* r )
    {
        rec = r;
        wstatus = 0;
    }

    virtual void set_content_type( const char* ct )
    {
        ap_set_content_type( rec, ct );
    }

    virtual uint64 get_session_id() const
    {
        const char* ssid = apr_table_get( rec->headers_in, "Session-Coid" );

        token::tonum<uint64> num(10);
        return ssid ? num.touint(ssid) : 0;
    }

    virtual void set_session_id( uint64 ssid )
    {
        tmpssid = ssid;

        apr_table_add( rec->headers_out, "Session-Coid", tmpssid.ptr() );
    }


    virtual uint binstream_attributes( bool in0out1 ) const
    {
        return fATTR_IO_FORMATTING | fATTR_HANDSHAKING;
    }

    virtual bool is_open() const        { return true; }
    virtual opcd read_until( const substring& ss, binstream* bout, uints max_size=UMAXS )
	{    return ersNOT_IMPLEMENTED; }


    virtual opcd write_raw( const void* p, uints& len )
    {
        if(!wstatus) {
            ap_send_http_header(rec);
            wstatus = 1;
        }

        len -= ap_rwrite( p, len, rec );
        return len ? ersRETRY : ersNOERR;
    }

    virtual opcd read_raw( void* p, uints& len )
    {
        long k = ap_get_client_block( rec, (char*)p, len );
        if( k < 0 )
            return ersFAILED;
        else if( k == 0 )
            return ersNO_MORE;

        len -= k;
        return len ? ersRETRY : ersNOERR;
    }

    virtual void flush()
    {
        if(wstatus) {
            ap_rflush(rec);
            wstatus = 0;
        }
    }

    virtual void acknowledge( bool eat=false )
    {
        if( rec->method_number == M_GET  ||  eat )
            ap_discard_request_body(rec);
        else if( rec->remaining > 0 )
            throw ersIO_ERROR "data left in input buffer";
    }

};


#endif //__MOD_COID__HTTPSTREAMAPACHE__HEADER_FILE__
